/** math.d - Basic math functions

Authors:
    Wei Li (oldrev@gmail.com)

Copyright:
    Copyright (C) 2007 The Dotmars Team.

License: BSD

 */

module dotmars.base.math;

import dotmars.base.typetraits;
import dotmars.runtime.stdclib.math;


//private extern(C) double floor(double x);
//private extern(C) double ceil(double x);


public const double E = 2.7182818284590452354;
public const double PI = 3.14159265358979323846;

public static T abs(T)(T value)
{
    return value < 0 ? -value : value; 
}


public static T square(T)(T x)
{
    return x * x;
}

public static double ceiling (double x)
{
    return .ceil(x);
}

public static double ceiling (float x)
{
    return .ceilf(x);
}

public static double ceiling (real x)
{
    return .ceill(x);
}

public static double floor(double x)
{
    return .floor(x);
}

public static double floor (float x)
{
    return .floorf(x);
}

public static double floor(real x)
{
    return .floorl(x);
}

public static long bigMul (int a, int b)
{
    return (cast(long)a * cast(long)b);
}

public static T divRem(T) (T a, T b, out T result)
{
    static assert(IsInteger!(T));
    result = (a % b);
    return cast(T)(a / b);
}

/*
   public static double ieeeRemainder (double x, double y)
   {
   double r;
   if (y == 0) return double.nan;
   r = x - (y * round(x / y));
   if (r != 0) return r;
   return (x > 0) ? 0: (BitConverter.Int64BitsToDouble (Int64.MinValue));
   }*/

public static double log (double a, double newBase)
{
    double result = log(a) / log(newBase);
    return (result == -0)? 0: result;
}

public static T max(T)(T x, T y)
{
    return x > y ? x : y;
}

public static T min(T)(T x, T y)
{
    return x < y ? x : y;
}


public static T truncate(T)(T x)
{
    if (x > 0.0) return floor (x);
    else if (x < 0.0) return ceiling (x);
    return x;
}

public static T sign(T)(T x)
{
    if (x > 0) return 1;
    return (x == 0) ? 0 : -1;
}

public static double round(double x)
{
    return .round(x);
}

public static float round(float x)
{
    return .roundf(x);
}

public static float round(real x)
{
    return .roundl(x);
}

public static double sin (double x)
{
    return .sin(x);
}

public static float sin(float x)
{
    return .sinf(x);
}

public static float sin(real x)
{
    return .sinl(x);
}

public static double cos(double x)
{
    return .cos(x);
}

public static float cos(float x)
{
    return .cosf(x);
}

public static float cos(real x)
{
    return .cosl(x);
}

public static double tan(double x)
{
    return .tan(x);
}

public static float tan(float x)
{
    return .tanf(x);
}

public static float tan(real x)
{
    return .tanl(x);
}

public static double sinh(double x)
{
    return .sinh(x);
}

public static float sinh(float x)
{
    return .sinhf(x);
}

public static real sinh(real x)
{
    return .sinhl(x);
}

public static double cosh(double x)
{
    return .cosh(x);
}

public static float cosh(float x)
{
    return .coshf(x);
}

public static real cosh(real x)
{
    return .coshl(x);
}

public static double tanh(double x)
{
    return .tanh(x);
}

public static float tanh(float x)
{
    return .tanhf(x);
}

public static real tanh(real x)
{
    return .tanhl(x);
}

public static double acos(double x)
{
    return .acos(x);
}

public static float acos(float x)
{
    return .acosf(x);
}

public static real acos(real x)
{
    return .acosl(x);
}

public static double asin(double x)
{
    return .asin(x);
}

public static float asin(float x)
{
    return .asinf(x);
}

public static real asin(real x)
{
    return .asinl(x);
}

public static double atan(double x)
{
    return .atan(x);
}

public static float atan(float x)
{
    return .atanf(x);
}

public static real atan(real x)
{
    return .atanl(x);
}

public static double atan2(double y, double x)
{
    return .atan2(y, x);
}

public static float atan2(float y, float x)
{
    return .atan2f(y, x);
}

public static real atan2(real y, real x)
{
    return .atan2l(y, x);
}


public static double exp(double x)
{
    return .exp(x);
}

public static float exp(float x)
{
    return .expf(x);
}

public static real exp(real x)
{
    return .expl(x);
}

public static double log(double x)
{
    return .log(x);
}

public static float log(float x)
{
    return .logf(x);
}

public static real log(real x)
{
    return .logl(x);
}

public static double log10(double x)
{
    return .log10(x);
}

public static float log10(float x)
{
    return .log10f(x);
}

public static real log10(real x)
{
    return .log10l(x);
}

public static double pow(double x, double y)
{
    return .pow(x, y);
}

public static float pow(float x, float y)
{
    return .powf(x, y);
}

public static real pow(real x, real y)
{
    return .powl(x, y);
}

public static double sqrt(double x)
{
    return .sqrt(x);
}

public static float sqrt(float x)
{
    return .sqrtf(x);
}

public static real sqrt(real x)
{
    return .sqrtl(x);
}


//mods
public static int mod(int x, int y)
{
    return x % y;
}

public static long mod(long x, long y)
{
    return x % y;
}

public static float mod(float x, float y)
{
    return .fmodf(x, y);
}

public static double mod(double x, double y)
{
    return .fmod(x, y);
}

public static real mod(real x, real y)
{
    return .fmodl(x, y);
}

////////////////////////////////////////////

public static float degToRad(float t)
{
    return PI * t / 180.0;
}

public static double degToRad(double t)
{
    return PI * t / 180.0;
}

public static real degToRad(real t)
{
    return PI * t / 180.0;
}


public static float radToDeg(float t)
{
    return 180.0 * t / PI;
}

public static double radToDeg(double t)
{
    return 180.0 * t / PI;
}

public static real radToDeg(real t)
{
    return 180.0 * t / PI;
}
